﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
//using System.Windows.Forms;
using System.Windows.Shapes;

namespace myCommon.WinAPI
{
    // =======================================================
    //
    //  M E S S A G E
    //
    // =======================================================
    /// <summary>
    /// 来源：https://www.cnblogs.com/kevinGao/archive/2011/10/30/2231524.html
    /// </summary>
    public static class Message
    {
        //   Windows 消息相关
        /**************************************************
         * 需要将下面的代码拷贝到主程序中，以便响应Windows的Message
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case ShareMemory.Client.WM_USER_DATAREADY:
                    //RecevieMessage(@"GlobalMyFileMappingObject");
                    this.listBox1.Items.Add(ShareMemory.Client.GetMessageFromShareMem(@"GlobalMyFileMappingObject"));
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        /***************************************************/

        /// <summary>
        /// 自定义的结构
        /// </summary>
        public struct My_lParam
        {
            public int i;
            public string s;
        }
        /// <summary>
        /// 使用COPYDATASTRUCT来传递字符串
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }

        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
            int Msg,            // 消息ID
            int wParam,         // 参数1
            int lParam          //参数2
        );



        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
            int Msg,            // 消息ID
            int wParam,         // 参数1
            ref My_lParam lParam //参数2
        );

        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
            int Msg,            // 消息ID
            int wParam,         // 参数1
            ref COPYDATASTRUCT lParam  //参数2
        );

        //消息发送API
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
            int Msg,            // 消息ID
            int wParam,         // 参数1
            int lParam            // 参数2
        );



        //消息发送API
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
            int Msg,            // 消息ID
            int wParam,         // 参数1
            ref My_lParam lParam //参数2
        );

        //异步消息发送API
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
            int Msg,            // 消息ID
            int wParam,         // 参数1
            ref COPYDATASTRUCT lParam  // 参数2
        );

        


        public static void Init()
        {

        }

        public static void TellClentDataReady(IntPtr ClientHandle)
        {
            if (ClientHandle != IntPtr.Zero)
            {
                WinAPI.Message.SendMessage(ClientHandle, WinAPI.WM_List.WM_USER_DATAREADY, 0, 0);
            }
        }
    }

    public static class FileMapping
    {
        /// <summary>创建一个文件映射内核对象
        /// </summary>
        /// <param name="hFile"></param>
        /// <param name="lpAttributes"></param>
        /// <param name="flProtect"></param>
        /// <param name="dwMaximumSizeLow"></param>
        /// <param name="dwMaximumSizeHigh"></param>
        /// <param name="lpName"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeLow, int dwMaximumSizeHigh, string lpName);

        /// <summary> 把文件数据映射到进程的地址空间
        /// </summary>
        /// <param name="hFileMappingObject"></param>
        /// <param name="dwDesiredAccess"></param>
        /// <param name="dwFileOffsetHigh"></param>
        /// <param name="dwFileOffsetLow"></param>
        /// <param name="dwNumBytesToMap"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true)]
        public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, IntPtr dwNumBytesToMap);

        [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
        [DllImport("kernel32", SetLastError = true)]
        public static extern bool FlushViewOfFile(IntPtr lpBaseAddress, IntPtr dwNumBytesToFlush);

        [DllImport("kernel32.dll", EntryPoint = "OpenFileMapping", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr OpenFileMapping(int dwDesiredAccess, bool bInheritHandle, String lpName);

        public enum MapProtection
        {
            PageNone = 0x00000000,
            // protection - mutually exclusive, do not or
            PageReadOnly = 0x00000002,
            PageReadWrite = 0x00000004,
            PageWriteCopy = 0x00000008,
            // attributes - or-able with protection
            SecImage = 0x01000000,
            SecReserve = 0x04000000,
            SecCommit = 0x08000000,
            SecNoCache = 0x10000000,
        }
        public enum MapAccess
        {
            FileMapCopy = 0x0001,
            FileMapWrite = 0x0002,
            FileMapRead = 0x0004,
            FileMapAllAccess = 0x001f,
        }
        /*
        struct SECURITY_ATTRIBUTES
        { // sa 
            long nLength;
            IntPtr lpSecurityDescriptor;
            bool bInheritHandle;
        }
         */

    }

    public static partial class Process
    {
        [DllImport("kernel32", SetLastError = true)]
        public static extern bool CloseHandle(IntPtr handle);

        public static IntPtr GetClientMainFromHandle(string processName)
        {
            //string name = "DDEClient";

            //General.LogFunc.LogWrite("ProcessName is:"+processName);
            System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(processName);

            if (process.Length == 0) return IntPtr.Zero;
            else
            {
                //handl = process[0].MainWindowHandle;
                IntPtr handl = new IntPtr(process[0].Id);
                //General.LogFunc.LogWrite("We Found " + process.Length.ToString() + " processes, it's ID is: "+handl.ToString());
                return handl;
            }
            //else return IntPtr.Zero;
            //return process.MainWindowHandle;
        }

    }
    public static class Others
    {

    }

    public static class Window
    {
        #region GetWindowCapture的dll引用
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowRect(IntPtr hWnd, ref System.Drawing.Rectangle rect);

        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateCompatibleDC(
         IntPtr hdc // handle to DC
         );
        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateCompatibleBitmap(
         IntPtr hdc,         // handle to DC
         int nWidth,      // width of bitmap, in pixels
         int nHeight      // height of bitmap, in pixels
         );
        [DllImport("gdi32.dll")]
        private static extern IntPtr SelectObject(
         IntPtr hdc,           // handle to DC
         IntPtr hgdiobj    // handle to object
         );
        [DllImport("gdi32.dll")]
        private static extern int DeleteDC(
         IntPtr hdc           // handle to DC
         );
        [DllImport("user32.dll")]
        private static extern bool PrintWindow(
         IntPtr hwnd,                // Window to copy,Handle to the window that will be copied.
         IntPtr hdcBlt,              // HDC to print into,Handle to the device context.
         UInt32 nFlags               // Optional flags,Specifies the drawing options. It can be one of the following values.
         );
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowDC(
         IntPtr hwnd
         );
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern IntPtr DeleteObject(IntPtr hObject);

        //[DllImport("gdi32")]
        //public static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO_FLAT bmi, int iUsage, ref int ppvBits, IntPtr hSection, int dwOffset);

        #endregion

        //public static Bitmap GetWindowCapture(IntPtr hWnd)
        //{
        //    IntPtr hscrdc = GetWindowDC(hWnd);
        //    System.Drawing.Rectangle windowRect = new System.Drawing.Rectangle();
        //    GetWindowRect(hWnd, ref windowRect);
        //    int width = Math.Abs(windowRect.X - windowRect.Width);
        //    int height = Math.Abs(windowRect.Y - windowRect.Height);

        //    IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, width, height); //这里创建了一个空的BMP文件
        //    IntPtr hmemdc = CreateCompatibleDC(hscrdc);

        //    SelectObject(hmemdc, hbitmap);
        //    bool res=PrintWindow(hWnd, hmemdc, 0);
        //    if (res)
        //    {

        //    }

        //    Bitmap bmp =new Bitmap( Image.FromHbitmap(hbitmap));
            
        //    DeleteDC(hscrdc);//删除用过的对象
        //    DeleteDC(hmemdc);//删除用过的对象
        //    return bmp;
        //}
        public static Bitmap GetWindow(IntPtr hWnd)    //hWnd可以是窗口、控件等的handle，因此这种方法截我们想要的部分非常好用。
        {
            IntPtr hscrdc = GetWindowDC(hWnd);

            System.Drawing.Rectangle windowRect = new System.Drawing.Rectangle();
            GetWindowRect(hWnd, ref windowRect);
            int width = Math.Abs(windowRect.X - windowRect.Width);
            int height = Math.Abs(windowRect.Y - windowRect.Height);

            //Control control = Control.FromHandle(hWnd);
            IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, width, height);
            IntPtr hmemdc = CreateCompatibleDC(hscrdc);
            SelectObject(hmemdc, hbitmap);
            bool re = PrintWindow(hWnd, hmemdc, 0);
            Bitmap bmp = null;
            if (re)
            {
                bmp = Bitmap.FromHbitmap(hbitmap);
            }
            DeleteObject(hbitmap);
            DeleteDC(hmemdc);//删除用过的对象       
            ReleaseDC(hWnd, hscrdc);
            return bmp;
        }
        /*
        public static Bitmap mycap(Graphics g, IntPtr hWnd)
        {
            Graphics g;
            Bitmap bmp = new Bitmap(800, 600, g);
            Graphics memoryGraphics = Graphics.FromImage(bmp);
            IntPtr dc = memoryGraphics.GetHdc();
            bool success = PrintWindow(hWnd, dc, 0);
            memoryGraphics.ReleaseHdc(dc);
            return bmp;
        }*/
        public static Bitmap Capture(IntPtr handle)
        {
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle();
            GetWindowRect(handle, ref rect);
            Bitmap Bmp = new Bitmap(rect.Right - rect.Left, rect.Bottom - rect.Top);

            Graphics memoryGraphics = Graphics.FromImage(Bmp);
            IntPtr dc = memoryGraphics.GetHdc();
            bool success = PrintWindow(handle, dc, 0);
            memoryGraphics.ReleaseHdc(dc);

            return Bmp;
        }

    }

    public static class API_Structure
    {


    }
}